﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using HIWSystem.Common;
using HIWSystem.Helpers;
using HIWSystem.Models;
using Microsoft.Win32;
using Microsoft.WindowsAPICodePack.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace HIWSystem.ViewModel
{
    public class ShipReportViewModel : ViewModelBase
    {
        #region 属性

        private List<SNEntity> lstSqlSnEntity = null;
        private int errorCounts = 0;
        private bool isEnabledBatchReportButton = true;
        private bool isEnabledGenerateButton = true;
        private Visibility isVisibleLoadingAnitation = Visibility.Collapsed;
        private int preGenerateCounts = 0;
        private ObservableCollection<SNEntity> preGenerateSns;
        private string processMsg;
        private Brush processMsgForeground;
        private string savePath;

        /// <summary>
        /// 异常序列号数量
        /// </summary>
        public int ErrorCounts
        {
            get { return errorCounts; }
            set { errorCounts = value; this.RaisePropertyChanged(() => ErrorCounts); }
        }

        /// <summary>
        /// 是否启用批量导入按钮
        /// </summary>
        public bool IsEnabledBatchReportButton
        {
            get { return isEnabledBatchReportButton; }
            set { isEnabledBatchReportButton = value; this.RaisePropertyChanged(() => IsEnabledBatchReportButton); }
        }

        /// <summary>
        /// 是否启用生成报告按钮
        /// </summary>
        public bool IsEnabledGenerateButton
        {
            get { return isEnabledGenerateButton; }
            set { isEnabledGenerateButton = value; this.RaisePropertyChanged(() => IsEnabledGenerateButton); }
        }

        /// <summary>
        /// 是否显示加载动画
        /// </summary>
        public Visibility IsVisibleLoadingAnitation
        {
            get { return isVisibleLoadingAnitation; }
            set { isVisibleLoadingAnitation = value; this.RaisePropertyChanged(() => IsVisibleLoadingAnitation); }
        }

        /// <summary>
        /// 预生成报告序列号数量
        /// </summary>
        public int PreGenerateCounts
        {
            get { return preGenerateCounts; }
            set { preGenerateCounts = value; this.RaisePropertyChanged(() => PreGenerateCounts); }
        }

        /// <summary>
        /// 预生成报告序列号
        /// </summary>
        public ObservableCollection<SNEntity> PreGenerateSns
        {
            get { return preGenerateSns; }
            set { preGenerateSns = value; this.RaisePropertyChanged(() => PreGenerateSns); }
        }

        /// <summary>
        /// 过程信息文本
        /// </summary>
        public string ProcessMsg
        {
            get { return processMsg; }
            set { processMsg = value; this.RaisePropertyChanged(() => ProcessMsg); }
        }

        /// <summary>
        /// 过程信息的字体颜色
        /// </summary>
        public Brush ProcessMsgForeground
        {
            get { return processMsgForeground; }
            set { processMsgForeground = value; this.RaisePropertyChanged(() => ProcessMsgForeground); }
        }

        /// <summary>
        /// 报告保存路径
        /// </summary>
        public string SavePath
        {
            get { return savePath; }
            set { savePath = value; this.RaisePropertyChanged(() => SavePath); }
        }

        private double progressBarValue;

        /// <summary>
        /// 进度条当前值
        /// </summary>
        public double ProgressBarValue
        {
            get { return progressBarValue; }
            set { progressBarValue = value; this.RaisePropertyChanged(() => ProgressBarValue); }
        }

        private double progressBarMaximum = 100;

        /// <summary>
        /// 进度条最大值
        /// </summary>
        public double ProgressBarMaximum
        {
            get { return progressBarMaximum; }
            set { progressBarMaximum = value; this.RaisePropertyChanged(() => ProgressBarMaximum); }
        }

        private ObservableCollection<string> errorSns;

        /// <summary>
        /// 异常序列号
        /// </summary>
        public ObservableCollection<string> ErrorSns
        {
            get { return errorSns; }
            set { errorSns = value; this.RaisePropertyChanged(() => ErrorSns); }
        }

        #endregion 属性

        #region 命令

        private RelayCommand batchReportCmd;
        private RelayCommand browseCmd;

        private RelayCommand generateCmd;

        public RelayCommand BatchReportCmd
        {
            get
            {
                batchReportCmd = batchReportCmd ?? new RelayCommand(BatchReportAsync);
                return batchReportCmd;
            }
            set { batchReportCmd = value; }
        }

        public RelayCommand BrowseCmd
        {
            get
            {
                browseCmd = browseCmd ?? new RelayCommand(Browse);
                return browseCmd;
            }
            set { browseCmd = value; }
        }

        public RelayCommand GenerateCmd
        {
            get
            {
                generateCmd = generateCmd ?? new RelayCommand(GenerateAsync);
                return generateCmd;
            }
            set { generateCmd = value; }
        }

        private RelayCommand loadPageCmd;

        public RelayCommand LoadPageCmd
        {
            get
            {
                loadPageCmd = loadPageCmd ?? new RelayCommand(LoadedPage);
                return loadPageCmd;
            }
            set { loadPageCmd = value; }
        }

        #endregion 命令

        #region 方法

        /// <summary>
        /// 页面加载
        /// </summary>
        private void LoadedPage()
        {
            SavePath = Global.AppConfigs?.ShipInfo?.FullReportDirectory; //根据配置项初始化报告保存路径
        }

        /// <summary>
        /// 添加过程信息
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="color">字体颜色</param>
        private void AddProcessInfo(string msg, Brush color)
        {
            Application.Current.Dispatcher.BeginInvoke((Action)(() =>
            {
                ProcessMsgForeground = color;
                ProcessMsg = msg;
            }));
        }

        /// <summary>
        /// 批量导入待生成报告的序列号
        /// </summary>
        private async void BatchReportAsync()
        {
            string batchDataFilePath = string.Empty; //批量数据文件路径
            StringBuilder errorMsg = new StringBuilder();//异常信息
            bool result = false;//验证结果
            await Task.Run(() =>
            {
                try
                {
                    AddProcessInfo("******************************开始处理**************************************", Brushes.Blue);
                    IsVisibleLoadingAnitation = Visibility.Visible; //显示加载动画
                    SetButtonEnableState(false);//禁用按钮
                    AddProcessInfo("正在选择批量报告文件...", Brushes.Black);
                    OpenFileDialog openFileDialog = new OpenFileDialog();
                    openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                    openFileDialog.Filter = "Excel文件（*.xls;*.xlsx）|*.xls;*.xlsx"; //"(*.xls, *.xlsx) | *.xls; *.xlsx ";
                    openFileDialog.Title = "选择批量报告文件";
                    if (openFileDialog.ShowDialog() == true)
                    {
                        batchDataFilePath = openFileDialog.FileName;
                        AddProcessInfo(string.Format("已选择批量报告文件，文件路径【{0}】", batchDataFilePath), Brushes.Green);
                        var excelHeaderAndEntityPropertyMapping = new Dictionary<string, string>();
                        excelHeaderAndEntityPropertyMapping.Add(nameof(SNEntity.SN), "序列号");
                        AddProcessInfo("正在验证导入的模板标题和数据上限...", Brushes.Black);
                        result = BusinessProcess.VerifyExcelTemplateHeaderAndDataUpperLimit(excelHeaderAndEntityPropertyMapping, batchDataFilePath, out errorMsg);
                        if (result)
                        {
                            AddProcessInfo("导入报告的模板标题和数据上限没有问题", Brushes.Green);
                            AddProcessInfo("正在将Excel数据添加到实体类型中...", Brushes.Black);
                            var excelEntities = BusinessProcess.ExcelToEntityList<SNEntity>(excelHeaderAndEntityPropertyMapping, batchDataFilePath, out errorMsg, 2);
                            //errorMsg为空表示表中的数据符合规范
                            if (errorMsg.ToString() == "" && excelEntities.Count > 0)
                            {
                                AddProcessInfo("验证导入的数据在系统中是否存在", Brushes.Black);
                                //将序列号基础表填充到实体集合中
                                lstSqlSnEntity = BusinessProcess.SqlTableToEntityConvert<SNEntity>("select * from vw_SN with(nolock)");
                                AddProcessInfo("正在循环检测Excel每行数据在系统中是否存在...", Brushes.Black);
                                int errorSnCount = 0;//异常的序列号数量(即系统中不存在的)
                                for (int i = 0; i < excelEntities.Count; i++)
                                {
                                    if (lstSqlSnEntity.Count(s => s.SN == excelEntities[i].SN) == 0)
                                    {
                                        errorMsg.AppendLine("Excel中第" + (i + 3) + "行的数据在系统中不存在,请检查数据填写是否有误?");
                                        errorSnCount += 1;
                                    }
                                }
                                AddProcessInfo(string.Format("检测完毕  总共【{0}】条 满足【{1}】条 不满足【{2}】条", excelEntities.Count, excelEntities.Count - errorSnCount, errorSnCount), Brushes.Green);
                                //errorMsg为空表示没有异常数据
                                if (errorMsg.ToString() == "")
                                {
                                    AddProcessInfo("检查完成！开始将数据添加到界面列表中...", Brushes.Black);
                                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                    {
                                        PreGenerateSns = new ObservableCollection<SNEntity>();
                                        foreach (var e in excelEntities)
                                        {
                                            PreGenerateSns.Add(e);
                                        }
                                        PreGenerateCounts = PreGenerateSns.Count;
                                    }));
                                    AddProcessInfo("******************************处理完成**************************************", Brushes.Blue);
                                }
                                else
                                {
                                    AddProcessInfo(errorMsg.ToString(), Brushes.Red);
                                }
                            }
                            else
                            {
                                AddProcessInfo(errorMsg.ToString(), Brushes.Red);
                            }
                        }
                        else
                        {
                            AddProcessInfo(errorMsg.ToString(), Brushes.Red);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(string.Format("批量导入序列号数据时出现错误【{0}】", ex.Message), ex);
                    MessageBox.Show("批量导入失败！", "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Error);
                    AddProcessInfo(string.Format("批量导入序列号数据时出现错误【{0}】", ex.Message), Brushes.Red);
                }
                finally
                {
                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                    {
                        SetButtonEnableState(true); //启用按钮
                        IsVisibleLoadingAnitation = Visibility.Collapsed;
                    }));
                }
            });
        }

        /// <summary>
        /// 选择保存路径
        /// </summary>
        private void Browse()
        {
            //打开文件夹对话框选择保存报告的文件夹路径
            var dialog = new CommonOpenFileDialog();
            dialog.IsFolderPicker = true;
            dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            CommonFileDialogResult result = dialog.ShowDialog();
            if (result == CommonFileDialogResult.Ok)
            {
                this.SavePath = dialog.FileName;
            }
            else
            {
                this.SavePath = "";
            }
        }

        /// <summary>
        /// 生成报告
        /// </summary>
        private async void GenerateAsync()
        {
            string ATEReportPNDirectorySection = string.Empty;//存放ATE报告的机种文件夹  E:\TestData\ATE Test Data\WaveLab\PassReports\AD-0707-01
            await Task.Run(() =>
            {
                try
                {
                    //判断是否选择保存路径
                    if ((SavePath ?? "") == "")
                    {
                        MessageBox.Show("保存的路径不能为空，请选择保存的路径。", "软件温馨提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                    //判断是否有待生成报告的序列号
                    if (PreGenerateCounts <= 0)
                    {
                        MessageBox.Show("没有待生成报告的序列号，请先点击批量导入按钮添加序列号。", "软件温馨提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                    SetButtonEnableState(false);//禁用按钮
                    AddProcessInfo("******************************开始批量生成报告**************************************", Brushes.Blue);
                    ErrorSns = new ObservableCollection<string>();
                    ErrorCounts = 0;
                    //迭代每一个序列号
                    for (int i = 0; i < PreGenerateSns.Count; i++)
                    {
                        ProgressBarValue = (i + 1) * 100 / PreGenerateCounts;
                        string strSN = PreGenerateSns[i].SN;
                        AddProcessInfo(string.Format("开始生成序列号【{0}】报告", strSN), Brushes.Black);

                        ////判断序列号是否已经出货
                        //bool ret = BusinessProcess.IsShiped(strSN);
                        //if (!ret)
                        //{
                        //    LogHelper.WriteShipLog(string.Format("序列号【{0}】还未出货,请先完成出货再生成报告.", strSN));
                        //    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                        //    {
                        //        ErrorSns.Add(strSN + "--未出货");
                        //        ErrorCounts += 1;
                        //    }));
                        //    continue;
                        //}
                        string strPN = lstSqlSnEntity.First(s => s.SN == strSN).PN;
                        var configIMDReportInfo = Global.AppConfigs?.ShipInfo?.IMDReportInfos?.Where(x => x.PN == (strPN ?? "")).FirstOrDefault();
                        //检测配置文件中是否包含相关机种的IMD基础配置
                        if (configIMDReportInfo == null)
                        {
                            LogHelper.WriteShipLog(string.Format("AppConfig.cfg配置文件中不存在该机种【{0}】的IMD报告基础配置。", strPN));
                            Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                            {
                                ErrorSns.Add(strSN + "--" + string.Format("AppConfig.cfg配置文件中不存在该机种【{0}】的IMD报告基础配置。", strPN));
                                ErrorCounts += 1;
                            }));
                            continue;
                        }
                        //判断序列号报告是否已经存在
                        if (!File.Exists(Path.Combine(SavePath,strPN+ "/"+strSN + ".xls")))
                        {
                            ATEReportPNDirectorySection = Path.Combine(Global.AppConfigs?.ShipInfo?.ATEReportDirectory, strPN);
                            if (!Directory.Exists(ATEReportPNDirectorySection))
                            {
                                LogHelper.WriteShipLog(string.Format("ATE原始数据的机种目录部分【{0}】不存在,请检查路径配置是否正确!", ATEReportPNDirectorySection));
                                Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                {
                                    ErrorSns.Add(strSN + "--" + string.Format("ATE原始数据的机种目录部分【{0}】不存在,请检查路径配置是否正确!", ATEReportPNDirectorySection));
                                    ErrorCounts += 1;
                                }));
                                continue;
                            }
                            var direcInfo = new DirectoryInfo(ATEReportPNDirectorySection);
                            //查找特定格式的目录，其它目录会被过滤掉
                            string searchPattern = string.Empty;//搜索的模式
                            searchPattern = "^" + strSN + "_SParTest_\\d*±\\d*°C_" +
                            "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))" + //匹配年月日部分 20220827
                            "T" + //匹配字符T
                            "([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])$"; //匹配时间部分092352
                            var regex = new Regex(searchPattern);
                            var direcInfos = direcInfo.GetDirectories();
                            var targetSnDirecFullNames = new List<string>(); //找到序列号所有的测试的目录 目录--HIW22352AAC00077_SParTest_20±5°C_20220825T152356
                                                                             //一个序列号可能要测试多变，我们把所有的目录依次遍历出来
                            foreach (var d in direcInfos)
                            {
                                if (regex.IsMatch(d.Name))
                                    targetSnDirecFullNames.Add(d.FullName);
                            }
                            if (targetSnDirecFullNames.Count <= 0)
                            {
                                LogHelper.WriteShipLog(string.Format("在这个路径下【{0}】没有找到序列号测试目录!", ATEReportPNDirectorySection));
                                Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                {
                                    ErrorSns.Add(strSN + "--" + string.Format("在这个路径下【{0}】没有找到序列号测试目录!", ATEReportPNDirectorySection));
                                    ErrorCounts += 1;
                                }));
                                continue;
                            }
                            /*
                             FullName:C:\Users\elc\Desktop\PassReports\AD-0708-03\HIW22352AAC00755_SParTest_20±5°C_20220825T152557
                             1.找到路径最后一部分【HIW22352AAC00755_SParTest_20±5°C_20220825T152557】的起始字符的位置即【H】
                             2.从最后一部分里面截取出时间部分根据时间逆序排序进而找出最近一次测试记录
                             3.将时间部分中‘T’字符去掉防止排序出现错误
                             */
                            string latestTestSnDirecFullName = targetSnDirecFullNames.OrderByDescending(x => x.Substring(x.LastIndexOf('\\') + 1).Split('_')[3].Replace("T", "")).FirstOrDefault();//
                                                                                                                                                                                                   //C:\Users\elc\Desktop\PassReports\AD-0708-03\HIW22352AAC00711_SParTest_20±5°C_20220825T152244
                            searchPattern = "^" + strPN ?? "" + "_" + //匹配机种
                            strSN ?? "" + "_" + //匹配序列号
                            "_SParTest_Passed_" + //匹配测试结果部分
                            "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))" + //匹配年月日部分 20220827
                            "T" + //匹配字符T
                            "([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])" + //匹配时间部分092352
                            "\\.xls$"; //匹配文件格式
                            IEnumerable<string> lstSnTestReportFullName = null;//测试报告文件名
                            lstSnTestReportFullName = Directory.GetFiles(latestTestSnDirecFullName + "\\", "*.xls").Where(x => Regex.IsMatch(x.Substring(x.LastIndexOf('\\') + 1), searchPattern));
                            if (lstSnTestReportFullName.Count() <= 0)
                            {
                                Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                {
                                    ErrorSns.Add(strSN + "--" + string.Format("在这个路径下【{0}】没有找到序列号测试报告!", latestTestSnDirecFullName));
                                    ErrorCounts += 1;
                                }));
                                continue;
                            }
                            //筛选出最后一次测试的报告名称和之前的目录合并-->C:\Users\elc\Desktop\PassReports\AD-0708-03\HIW22352AAC00711_SParTest_20±5°C_20220825T152244\AD-0708-03_HIW22352AAC00711_SParTest_Passed_20220825T152244.xls
                            string strLatestTestReportFullName = lstSnTestReportFullName.OrderByDescending(x => x.Substring(x.LastIndexOf('\\') + 1).Split('_')[4].Replace("T", "")).FirstOrDefault();
                            string strFullReportPNDirec = Path.Combine(SavePath, strPN);
                            //如果路径不存在就创建
                            if (!Directory.Exists(strFullReportPNDirec))
                                Directory.CreateDirectory(strFullReportPNDirec);
                            //最后一次测试报告文件名称
                            string strSnLatestTestReportFileName = strLatestTestReportFullName.Substring(strLatestTestReportFullName.LastIndexOf('\\') + 1);
                            //完整报告路径
                            string strFullReportPath = Path.Combine(strFullReportPNDirec, strSN + ".xls");// Path.Combine(strFullReportPNDirec, strSnLatestTestReportFileName);  2023-3-8 修改一版 最终文件名以输入的序列号为准
                            var fullReportPathFileInfo = new FileInfo(strFullReportPath);
                            //目标路径不存在就创建
                            if (!fullReportPathFileInfo.Exists)
                                fullReportPathFileInfo.Create().Close();
                            //先关闭Excel
                            BusinessProcess.KillProcess("EXCEL");
                            File.Copy(strLatestTestReportFullName, strFullReportPath, true);
                            //文件已经拷贝成功下一步是打开添加IMD内容
                            AddProcessInfo(string.Format("文件已经成功拷贝到路径【{0}】下", strFullReportPNDirec), Brushes.Black);

                            //首先判断此序列号流程中是否包含IMD测试工站
                            if (BusinessProcess.IsContainsIMDTestStation(strSN))
                            {
                                AddProcessInfo("开始添加IMD信息", Brushes.Black);
                                //var configIMDReportInfo = Global.AppConfigs?.ShipInfo?.IMDReportInfos?.Where(x => x.PN == (strPN ?? "")).FirstOrDefault();

                                //将IMD信息插入到ATE原始报告中的哪一行哪一列
                                int intStartRowInATEReport = 0, intStartColumnInATEReport = 0;
                                intStartRowInATEReport = configIMDReportInfo.StartRowInATEReport;
                                intStartColumnInATEReport = configIMDReportInfo.StartColumnInATEReport;
                                //获取系统中IMD测试信息
                                DataTable dtIMD = new DataTable();
                                var entity = new TrackingEntity { Sn = (strSN ?? ""), TestSequence = "1" };
                                BusinessProcess.QueryIMDDetails(entity, out dtIMD);
                                //判断有没有查询到互调工站信息
                                if (dtIMD.Rows.Count <= 0)
                                {
                                    LogHelper.WriteShipLog(string.Format("此序列号【{0}】没有查询到互调工站测试信息!", strSN ?? ""));
                                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                    {
                                        ErrorSns.Add(strSN + "--" + string.Format("此序列号【{0}】没有查询到互调工站测试信息!", strSN ?? ""));
                                        ErrorCounts += 1;
                                    }));
                                    continue;
                                }
                                else
                                {
                                    //判断互调每个站位的测试基础信息(TestValue,UpperLimit,LowerLimit)是否完整
                                    for (int j = 0; j < dtIMD.Rows.Count; j++)
                                    {
                                        var testValue = dtIMD.Rows[j]["TestValue"].ToString();
                                        var upperLimit = dtIMD.Rows[j]["UpperLimit"].ToString();
                                        var lowerLimit = dtIMD.Rows[j]["LowerLimit"].ToString();
                                        var station = dtIMD.Rows[j]["Station"].ToString();
                                        if (testValue == "" || upperLimit == "" || lowerLimit == "")
                                        {
                                            LogHelper.WriteShipLog(string.Format("此序列号【{0}】互调工站【{1}】基础信息【测试值:{2},上限:{3},下限:{4}】不完整!", strSN ?? "", station, testValue, upperLimit, lowerLimit));
                                            Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                            {
                                                ErrorSns.Add(strSN + "--" + string.Format("此序列号【{0}】互调工站【{1}】基础信息【测试值:{2},上限:{3},下限:{4}】不完整!", strSN ?? "", station, testValue, upperLimit, lowerLimit));
                                                ErrorCounts += 1;
                                            }));
                                            goto Next; //直接跳转到第一层循环,进行下一个序列号。
                                        }
                                    }
                                }
                                //创建操作EXCEL相关对象
                                Microsoft.Office.Interop.Excel.Application excelApp = null;
                                Microsoft.Office.Interop.Excel.Workbook excelWB = null;
                                Microsoft.Office.Interop.Excel.Worksheet excelWS = null;
                                Microsoft.Office.Interop.Excel.Range excelRg = null;
                                try
                                {
                                    excelApp = new Microsoft.Office.Interop.Excel.Application();
                                    excelWB = excelApp.Workbooks.Open(strFullReportPath);   //创建工作簿（WorkBook：即Excel文件主体本身）
                                    excelWS = (Microsoft.Office.Interop.Excel.Worksheet)excelWB.Worksheets[1];   //创建工作表（即Excel里的子表sheet） 1表示在子表sheet1里进行数据导出
                                    excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport] = "Index";
                                    excelRg = excelWS.Range[excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport], excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 1]];
                                    excelRg.Merge();
                                    excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 2] = "Test Item Description：";
                                    excelRg = excelWS.Range[excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 2], excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 7]];
                                    excelRg.Merge();
                                    excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 8] = "High";
                                    excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 9] = "Low";
                                    excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 10] = "Measured Value";
                                    excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport + 11] = "Result";
                                    //控制行数
                                    for (int k = 0; k < dtIMD.Rows.Count; k++)
                                    {
                                        //添加Index
                                        excelWS.Cells[intStartRowInATEReport + k + 1, intStartColumnInATEReport] = k + 1;
                                        //添加Test Item
                                        excelWS.Cells[intStartRowInATEReport + k + 1, intStartColumnInATEReport + 2] = dtIMD.Rows[k]["Station"].ToString();
                                        //添加上限
                                        excelWS.Cells[intStartRowInATEReport + k + 1, intStartColumnInATEReport + 8] = dtIMD.Rows[k]["UpperLimit"].ToString();
                                        //添加下限
                                        excelWS.Cells[intStartRowInATEReport + k + 1, intStartColumnInATEReport + 9] = dtIMD.Rows[k]["LowerLimit"].ToString();
                                        //添加测试值
                                        excelWS.Cells[intStartRowInATEReport + k + 1, intStartColumnInATEReport + 10] = dtIMD.Rows[k]["TestValue"].ToString();
                                        //添加结果
                                        excelWS.Cells[intStartRowInATEReport + k + 1, intStartColumnInATEReport + 11] = dtIMD.Rows[k]["Result"].ToString();
                                        //控制列数
                                    }
                                    int stopCellRowIndex = intStartRowInATEReport + dtIMD.Rows.Count;
                                    int stopCellColumnIndex = intStartColumnInATEReport + 11;
                                    excelRg = excelWS.Range[excelWS.Cells[intStartRowInATEReport, intStartColumnInATEReport], excelWS.Cells[stopCellRowIndex, stopCellColumnIndex]];
                                    excelRg.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; //设置单元格内容的对其方式
                                    excelRg.Borders.LineStyle = 1;//设置单元格边框
                                    excelWB?.Save();  //将其进行保存到指定的路径
                                }
                                catch (Exception ex)
                                {
                                    LogHelper.WriteShipLog(string.Format("打开Excel添加互调数据时出现异常【{0}】", ex.Message));
                                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                    {
                                        ErrorSns.Add(strSN + "--" + string.Format("打开Excel添加互调数据时出现异常【{0}】", ex.Message));
                                        ErrorCounts += 1;
                                    }));
                                }
                                finally
                                {
                                    //释放资源
                                    excelWB?.Close();
                                    excelApp?.Quit();
                                }
                            }
                        Next: continue;
                        }
                        else
                        {
                            AddProcessInfo(string.Format("序列号【{0}】的报告已经存在!", strSN), Brushes.Black);
                        } 
                    }
                    AddProcessInfo("******************************批量生成报告完成**************************************", Brushes.Blue);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(string.Format("批量生成出货报告数据时出现错误【{0}】", ex.Message), ex);
                    MessageBox.Show("批量生成报告失败！", "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Error);
                    AddProcessInfo(string.Format("批量生成出货报告数据时出现错误【{0}】", ex.Message), Brushes.Red);
                }
                finally
                {
                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                    {
                        SetButtonEnableState(true);//启用按钮
                    }));
                }
            });
        }

        /// <summary>
        /// 设置按钮的启用状态
        /// </summary>
        /// <param name="state">状态(true/false)</param>
        private void SetButtonEnableState(bool state)
        {
            Application.Current.Dispatcher.BeginInvoke((Action)(() =>
            {
                IsEnabledBatchReportButton = state;
                IsEnabledGenerateButton = state;
            }));
        }

        #endregion 方法
    }
}